package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

/**
 * @Author：武鑫鹏
 * @Project：springboot-aop-quickstart
 * @Date：2024/5/23 11:31
 * @Filename：MyAspect
 */

@Slf4j
// @Component
// @Aspect
public class MyAspect1 {

    // 掌握不同类型的通知及其特点
    // @Around：环绕通知，此注解标注的通知方法在目标方法前、后都被执行
    // @Before：前置通知，此注解标注的通知方法在目标方法前被执行
    // @After ：后置通知，此注解标注的通知方法在目标方法后被执行，无论是否有异常都会执行
    // @AfterReturning： 返回后通知，此注解标注的通知方法在目标方法后被执行，有异常不会执行
    // @AfterThrowing ： 异常后通知，此注解标注的通知方法发生异常后执行
    // @Pointcut : 切入点表达式，描述当前AOP程序针对于哪些方法编程

    @Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    // private：仅能在当前切面类中引用该表达式
    // public：在其他外部的切面类中也可以引用该表达式
    public void pointCut() {}

    // @Around("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @Around("pointCut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("环绕通知开始");
        Object result = joinPoint.proceed();
        log.info("环绕通知结束");
        return result;
    }

    // @Before("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @Before("pointCut()")
    public void beforeMethod(JoinPoint joinPoint) {
        log.info("before");
    }

    // @After("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @After("pointCut()")
    public void afterMethod(JoinPoint joinPoint) {
        log.info("after");
    }

    // @AfterReturning("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @AfterReturning("pointCut()")
    public void afterReturningMethod(JoinPoint joinPoint) {
        log.info("afterReturning");
    }

    // @AfterThrowing("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
    @AfterThrowing("pointCut()")
    public void afterThrowingMethod(JoinPoint joinPoint) {
        log.info("afterThrowing");
    }
}
